package com.yourcompany.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yourcompany.api.dto.FileQueryDTO;
import com.yourcompany.api.entity.SysFile;
import com.yourcompany.api.mapper.SysFileMapper;
import com.yourcompany.api.service.SysFileService;
import com.yourcompany.api.storage.StorageService;
import com.yourcompany.api.vo.FileUploadVO;
import com.yourcompany.common.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService {

    @Autowired
    @Qualifier("localStorageService")
    private StorageService storageService;

    @Override
    public IPage<SysFile> pageFiles(IPage<SysFile> page, FileQueryDTO queryDTO) {
        LambdaQueryWrapper<SysFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(queryDTO.getFileName()), SysFile::getFileName, queryDTO.getFileName())
                .eq(StringUtils.isNotBlank(queryDTO.getFileType()), SysFile::getFileType, queryDTO.getFileType())
                .eq(StringUtils.isNotBlank(queryDTO.getBusinessType()), SysFile::getBusinessType, queryDTO.getBusinessType())
                .eq(StringUtils.isNotBlank(queryDTO.getBusinessId()), SysFile::getBusinessId, queryDTO.getBusinessId())
                .eq(StringUtils.isNotBlank(queryDTO.getStorageType()), SysFile::getStorageType, queryDTO.getStorageType())
                .ge(StringUtils.isNotBlank(queryDTO.getStartTime()), SysFile::getCreateTime, queryDTO.getStartTime())
                .le(StringUtils.isNotBlank(queryDTO.getEndTime()), SysFile::getCreateTime, queryDTO.getEndTime())
                .orderByDesc(SysFile::getCreateTime);
        return page(page, wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileUploadVO uploadFile(MultipartFile file, String businessType, String businessId) {
        try {
            String fileName = file.getOriginalFilename();
            String fileType = FileUtil.extName(fileName);
            String fileMd5 = MD5.create().digestHex(file.getInputStream());
            
            // 检查文件是否已存在
            LambdaQueryWrapper<SysFile> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysFile::getFileMd5, fileMd5)
                    .eq(SysFile::getFileName, fileName);
            SysFile existFile = getOne(wrapper);
            if (existFile != null) {
                FileUploadVO vo = new FileUploadVO();
                vo.setFileId(existFile.getId());
                vo.setFileName(existFile.getFileName());
                vo.setFileUrl(existFile.getFileUrl());
                vo.setFileSize(existFile.getFileSize());
                return vo;
            }
            
            // 生成存储路径
            String path = generateFilePath(businessType, fileType);
            
            // 上传文件
            String fileUrl = storageService.upload(file, path);
            
            // 保存文件信息
            SysFile sysFile = new SysFile();
            sysFile.setFileName(fileName);
            sysFile.setFilePath(path);
            sysFile.setFileUrl(fileUrl);
            sysFile.setFileType(fileType);
            sysFile.setFileSize(file.getSize());
            sysFile.setFileMd5(fileMd5);
            sysFile.setBusinessType(businessType);
            sysFile.setBusinessId(businessId);
            sysFile.setStorageType("local");
            save(sysFile);
            
            FileUploadVO vo = new FileUploadVO();
            vo.setFileId(sysFile.getId());
            vo.setFileName(sysFile.getFileName());
            vo.setFileUrl(sysFile.getFileUrl());
            vo.setFileSize(sysFile.getFileSize());
            return vo;
        } catch (IOException e) {
            throw new BusinessException("文件上传失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FileUploadVO> batchUploadFiles(MultipartFile[] files, String businessType, String businessId) {
        List<FileUploadVO> results = new ArrayList<>();
        for (MultipartFile file : files) {
            results.add(uploadFile(file, businessType, businessId));
        }
        return results;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFile(Long id) {
        SysFile file = getById(id);
        if (file != null) {
            storageService.delete(file.getFilePath());
            removeById(id);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByBusiness(String businessType, String businessId) {
        LambdaQueryWrapper<SysFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysFile::getBusinessType, businessType)
                .eq(SysFile::getBusinessId, businessId);
        
        list(wrapper).forEach(file -> {
            storageService.delete(file.getFilePath());
        });
        
        remove(wrapper);
    }
    
    /**
     * 生成文件存储路径
     */
    private String generateFilePath(String businessType, String fileType) {
        return businessType + "/"
                + DateUtil.format(DateUtil.date(), "yyyy/MM/dd") + "/"
                + UUID.randomUUID().toString().replace("-", "")
                + "." + fileType;
    }
} 